package com.example.spotitube.Connection;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URLEncoder;
import java.util.ArrayList;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;

import com.example.spotitube.Model.Track;
import com.example.spotitube.View.MainActivity;


public class Connection extends AsyncTask<Object, Integer, Integer>{
	
	private Handler				handler;
	private ArrayList<Track>	tracks;
	
	private ArrayList<String>	possibleMatches;
	
	
	public Connection( Handler handler ) {
		this.handler = handler;
		
		tracks = new ArrayList<Track>();
		possibleMatches = new ArrayList<String>();
	}
	
	
	public static boolean hasInternet( Context ctx ) {
		NetworkInfo info = ( NetworkInfo ) ( ( ConnectivityManager ) ctx.getSystemService( Context.CONNECTIVITY_SERVICE ) )
				.getActiveNetworkInfo();
		if( info == null || !info.isConnected() ){
			return false;
		}
		return true;
	}
	
	
	@Override
	protected Integer doInBackground( Object... values ) {
		try{
			String typeOfSearch = ( String ) values[1];
			if( typeOfSearch.equals( "artist" ) ){
				// get the artist filled in and make it urlencoded to avoid
				// errors with spaces for example
				String searchedFor = ( String ) values[0].toString();
				String encodedArtist = URLEncoder.encode( searchedFor );
				
				// search for the artist the user specified to see if it exists,
				// otherwise give suggestions
				JSONObject res = getJson( "http://ws.spotify.com/search/1/artist.json?q=" + encodedArtist );
				JSONArray artistsInJson = res.getJSONArray( "artists" );
				// see if matches < 5 and get that amount of artists
				int counter = 5;
				if( artistsInJson.length() < counter ){
					counter = artistsInJson.length();
				}
				for( int i = 0; i < counter; i++ ){
					JSONObject artist = artistsInJson.getJSONObject( i );
					String artistName = artist.getString( "name" );
					
					// if first one is a full match then dont show suggestions
					// and
					// search directly
					if( i == 0 && artistName.equalsIgnoreCase( searchedFor ) ){
						res = getJson( "http://ws.spotify.com/search/1/track.json?page=1&q=artist:" + encodedArtist );
						JSONArray tracksInJson = res.getJSONArray( "tracks" );
						
						for( int y = 0; y < tracksInJson.length(); y++ ){
							JSONObject track = tracksInJson.getJSONObject( y );
							
							// get the album info
							JSONObject album = track.getJSONObject( "album" );
							int released = album.getInt( "released" );
							String albumName = album.getString( "name" );
							
							// get the track info
							String trackName = track.getString( "name" );
							double popularity = track.getDouble( "popularity" );
							int length = track.getInt( "length" );
							
							boolean match = false;
							for( Track t : tracks ){
								if( t.getTrackName().equals( trackName ) ){
									match = true;
								}
							}
							if( !match ){
								tracks.add( new Track( trackName, released, popularity, length, albumName ) );
								
								String encodedSearch = ( String ) URLEncoder.encode( artistName + " " + trackName );
								tracks.get( tracks.size() - 1 ).setEncodedSearch( encodedSearch );
							}
						}
						return MainActivity.PERFECT_MATCH;
					}
					possibleMatches.add( artistName );
				}
			} else if( typeOfSearch.equals( "album" ) ){
				String searchedFor = ( String ) values[0].toString();
				String encodedAlbum = URLEncoder.encode( searchedFor );
				
				JSONObject res1 = getJson( "http://ws.spotify.com/search/1/album.json?q=" + encodedAlbum );
				JSONArray albums = res1.getJSONArray( "albums" );
				if( albums.length() > 0 ){
					JSONObject theAlbum = albums.getJSONObject( 0 );
					String albumHref = theAlbum.getString( "href" );
					
					JSONObject res2 = getJson( "http://ws.spotify.com/lookup/1/.json?uri=" + albumHref + "&extras=trackdetail" );
					JSONObject album = res2.getJSONObject( "album" );
					int released = album.getInt( "released" );
					
					JSONArray tracksInJson = album.getJSONArray( "tracks" );
					
					for( int i = 0; i < tracksInJson.length(); i++ ){
						JSONObject track = tracksInJson.getJSONObject( i );
						
						// get the track info
						String trackName = track.getString( "name" );
						double popularity = track.getDouble( "popularity" );
						int length = track.getInt( "length" );
						
						// get the artist info
						JSONArray artists = track.getJSONArray( "artists" );
						JSONObject artist = artists.getJSONObject( 0 );
						String artistName = artist.getString( "name" );
						
						boolean match = false;
						for( Track t : tracks ){
							if( t.getTrackName().equals( trackName ) ){
								match = true;
							}
						}
						if( !match ){
							tracks.add( new Track( trackName, released, popularity, length, searchedFor ) );
							
							String encodedSearch = ( String ) URLEncoder.encode( artistName + " " + trackName );
							tracks.get( tracks.size() - 1 ).setEncodedSearch( encodedSearch );
						}
					}
				}
				
				return MainActivity.PERFECT_MATCH;
			}
			
		} catch( Exception e ){
			e.printStackTrace();
			return MainActivity.FAILED;
		}
		return MainActivity.MULTIPLE_MATCHES;
	}
	
	
	//
	// JSONObject res = getJson(
	// "http://ws.spotify.com/search/1/track.json?page=1&q=album:" +
	// encodedAlbum );
	// JSONArray tracksInJson = res.getJSONArray( "tracks" );
	//
	// for( int y = 0; y < tracksInJson.length(); y++ ){
	// JSONObject track = tracksInJson.getJSONObject( y );
	//
	// // get the album info
	// JSONObject album = track.getJSONObject( "album" );
	// int released = album.getInt( "released" );
	// String albumName = album.getString( "name" );
	//
	// // get the artist info
	// JSONArray artists = track.getJSONArray( "artists" );
	// JSONObject artist = artists.getJSONObject( 0 );
	// String artistName = artist.getString( "name" );
	//
	// // get the track info
	// String trackName = track.getString( "name" );
	// double popularity = track.getDouble( "popularity" );
	// int length = track.getInt( "length" );
	
	public static JSONObject getJson( String uri ) {
		try{
			StringBuilder builder = new StringBuilder();
			HttpClient client = new DefaultHttpClient();
			HttpGet httpGet = new HttpGet( uri );
			
			HttpResponse response = client.execute( httpGet );
			StatusLine statusLine = response.getStatusLine();
			int statusCode = statusLine.getStatusCode();
			
			if( statusCode == 200 ){
				HttpEntity entity = response.getEntity();
				InputStream content = entity.getContent();
				BufferedReader reader = new BufferedReader( new InputStreamReader( content ) );
				String line;
				
				while( ( line = reader.readLine() ) != null ){
					builder.append( line );
				}
			} else if( statusCode == 404 ){
				System.out.println( "404 ERROR" );
			}
			return new JSONObject( builder.toString() );
			
		} catch( ClientProtocolException e ){
			e.printStackTrace();
		} catch( IOException e ){
			e.printStackTrace();
		} catch( JSONException e ){
			e.printStackTrace();
		}
		return null;
	}
	
	
	@Override
	public void onPostExecute( Integer result ) {
		Message msg = new Message();
		msg.what = result;
		switch( result ){
			case MainActivity.PERFECT_MATCH:
				msg.obj = tracks;
				break;
			case MainActivity.MULTIPLE_MATCHES:
				msg.obj = possibleMatches;
				break;
			default:
				break;
		}
		handler.sendMessage( msg );
	}
	
}
